package ar.edu.unlu.sistemas.movirdroid.business.strategy.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import ar.edu.unlu.sistemas.movirdroid.business.index.IndexController;
import ar.edu.unlu.sistemas.movirdroid.business.strategy.ProcessQueryStrategy;
import ar.edu.unlu.sistemas.movirdroid.business.util.Constants;
import ar.edu.unlu.sistemas.movirdroid.business.util.IndexHelper;
import ar.edu.unlu.sistemas.movirdroid.business.util.Logger;
import ar.edu.unlu.sistemas.movirdroid.business.util.StringUtils;
import ar.edu.unlu.sistemas.movirdroid.business.vo.DocumentVO;
import ar.edu.unlu.sistemas.movirdroid.business.vo.TermFrecuencyVO;
import ar.edu.unlu.sistemas.ws.business.QueryResultVO;

public class ProcessQueryLocalStrategyImpl extends ProcessQueryStrategy {

	IndexController index = IndexController.getInstance();
	
	@Override
	public List<QueryResultVO> execute(String query) {
		List<QueryResultVO> queryResults = new ArrayList<QueryResultVO>();
		List<QueryResultVO> outResulsts = new LinkedList<QueryResultVO>();
		try {
			HashMap<String,TermFrecuencyVO> queryMap = IndexHelper.indexQuery(query);
			Iterator<DocumentVO> allDocs = index.findAllDocs().iterator();
			DocumentVO currentDoc;
			Iterator<String> queryTerms;
			TermFrecuencyVO queryTermVO;
			TermFrecuencyVO docTermVO;
			Collection<String> queryWordsSet = queryMap.keySet();
			String[] queryWordArr = StringUtils.fromObjArr2StrArr(queryWordsSet.toArray());
			while (allDocs.hasNext()) {
				queryTerms = queryWordsSet.iterator();
				currentDoc = allDocs.next();
				HashMap<String,TermFrecuencyVO> docMap = this.findTfsByDocAndWords(currentDoc,queryWordArr);
				if (docMap.containsKey(Constants.SQUARE_SUM_WORD)) {
					Double ac = new Double(0);
					while (queryTerms.hasNext()) {
						queryTermVO = queryMap.get(queryTerms.next());
						if (!Constants.SQUARE_SUM_WORD.equals(queryTermVO.getWord().getName())) {
							docTermVO = docMap.get(queryTermVO.getWord().getName());
							if (docTermVO != null) {
								ac += queryTermVO.getValue() * docTermVO.getValue();
							}
						}
					}
					ac = ac/(Math.sqrt(docMap.get(Constants.SQUARE_SUM_WORD).getValue())*Math.sqrt(queryMap.get(Constants.SQUARE_SUM_WORD).getValue()));
					queryResults.add(this.instanceResult(currentDoc.getName(),ac.floatValue()));
				}
			}
			outResulsts = this.filterResults(queryResults);
		} catch (Exception e) {
			Logger.logError(this.getClass().getSimpleName(), e.getMessage(), e);
		}
		return outResulsts;
	}
	
	protected QueryResultVO instanceResult(String docName, Float value) {
		return new QueryResultVO(docName,value);
	}
	
	private HashMap<String,TermFrecuencyVO> findTfsByDocAndWords(DocumentVO docVO, String[] words) {
		Iterator<TermFrecuencyVO> allTerms = index.findTFsByDocumentAndWords(docVO.getName(),words).iterator();
		HashMap<String,TermFrecuencyVO> termsMap = new HashMap<String,TermFrecuencyVO>();
		TermFrecuencyVO termVO;
		while (allTerms.hasNext()) {
			termVO = allTerms.next();
			termsMap.put(termVO.getWord().getName(), termVO);
		}
		return termsMap;
	}
}

